#include "cntr_user.h"

ControllerUser::ControllerUser(InterfaceUser * interface,cmd_user * cmd)
               : Controller(interface,cmd),interface(interface),cmd(cmd){
    MIN_OPT = 0;
    MAX_OPT = 4;
    MAX_TOLERANCE = 3;
}

int ControllerUser::execute(){
    int opcao = 0;
    stringstream ss;
    exception exc;
    bool tf = true;
    while(tf){
        try{
            opcao = 0;
            opcao = interface->chooseOpt();
            if(opcao>MAX_OPT || opcao<MIN_OPT){
                ss << endl << "opcao invalida :" << opcao << endl;
                interface->inform(ss.str());
                break;
            }
        }catch (exception& e){

            ss << endl << "Erro (ControllerUser.execute.try.chooseOpt):" << endl;
            ss << e.what() << endl;

            interface->inform(ss.str());
            break;
        }

        interface->inform(ss.str());
        ss.str(""); // limpar ss, caso contrario acumula mensagens.
                    // Usado apenas nesse ponto pq nos outros ocorre
                    // um break e o loop acaba

        switch(opcao){
            case 1:
                alterarNome();
                break;
            case 2:
                alterarSenha();
                break;
            case 3:
                alterarEndereco();
                break;
            case 4:
                apagarConta();
                break;
            default:
                tf = false;
                break;
        }
    }

    return 0;
}

int ControllerUser::alterarNome(){
    int error = 0;
    stringstream ss;
    string nome;
    Name name;

    while(true){
        try{
            interface->inform(interface->get_name);
            nome = interface->getString();
            name.set(nome);
            //interface->inform(identifier.get());//teste if ok
            break;
        }catch(invalid_argument ia){
            interface->inform(ia.what());
            error++;
            if(error>MAX_TOLERANCE){
                //throw(interface->err_tolerance);
            }
        }
    }

    User * user = new User();
    user->setName(name);

    cmd->setUser(user);

    cmd->setCmd(cmd_user::ALTERARNOME);
    try{
        Persistence::Instanciate()->Executar(cmd);
    }catch(string str){
        throw(str);
    }

    interface->inform(interface->alt_endereco_fim);

    return 0;
}

int ControllerUser::alterarSenha(){
    int error = 0;
    stringstream ss;
    string senha;
    Password password;

    while(true){
        try{
            interface->inform(interface->get_password);
            senha = interface->getString();
            password.set(senha);
            //interface->inform(identifier.get());//teste if ok
            break;
        }catch(invalid_argument ia){
            interface->inform(ia.what());
            error++;
            if(error>MAX_TOLERANCE){
                //throw(interface->err_tolerance);
            }
        }
    }

    User * user = new User();
    user->setPassword(password);

    cmd->setUser(user);

    cmd->setCmd(cmd_user::ALTERARSENHA);
    try{
        Persistence::Instanciate()->Executar(cmd);
    }catch(string str){
        throw(str);
    }

    interface->inform(interface->alt_endereco_fim);

    return 0;
}

int ControllerUser::alterarEndereco(){
    int error = 0;
    stringstream ss;
    string endereco;
    Address address;

    while(true){
        try{
            interface->inform(interface->get_address);
            endereco = interface->getString();
            address.set(endereco);
            //interface->inform(identifier.get());//teste if ok
            break;
        }catch(invalid_argument ia){
            interface->inform(ia.what());
            error++;
            if(error>MAX_TOLERANCE){
                //throw(interface->err_tolerance);
            }
        }
    }

    User * user = new User();
    user->setAddress(address);

    cmd->setUser(user);

    cmd->setCmd(cmd_user::ALTERARENDERECO);
    try{
        Persistence::Instanciate()->Executar(cmd);
    }catch(string str){
        throw(str);
    }

    interface->inform(interface->alt_endereco_fim);

    return 0;
}

int ControllerUser::apagarConta(){
    int error = 0;
    stringstream ss;

    cmd->setCmd(cmd_user::APAGARUSUARIO);
    try{
        Persistence::Instanciate()->Executar(cmd);
    }catch(string str){
        throw(str);
    }

    interface->inform(interface->apg_conta_fim);
    cin.get();
    exit (0);

    return 0;
}

/********************************************************/

ControllerAuth::ControllerAuth(InterfaceAuth * interface,cmd_auth * cmd)
               : Controller(interface,cmd),interface(interface),cmd(cmd){
    MIN_OPT = 0;
    MAX_OPT = 2;
    MAX_TOLERANCE = 3;
}

int ControllerAuth::execute(){
    int opcao = 0;
    stringstream ss;
    exception exc;
    bool tf = true;
    while(tf){
        try{
            opcao = 0;
            opcao = interface->chooseOpt();
            if(opcao>MAX_OPT || opcao<MIN_OPT){
                ss << endl << "opcao invalida :" << opcao << endl;
                interface->inform(ss.str());
                break;
            }
        }catch (exception& e){

            ss << endl << "Erro (ControllerUser.execute.try.chooseOpt):" << endl;
            ss << e.what() << endl;

            interface->inform(ss.str());
            break;
        }

        ss << endl << "opcao digitada:" << opcao << endl;
        interface->inform(ss.str());
        ss.str(""); // limpar ss, caso contrario acumula mensagens.
                    // Usado apenas nesse ponto pq nos outros ocorre
                    // um break e o loop acaba

        switch(opcao){
            case 1:
                fazerLogin();
                break;
            case 2:
                cadastrar();
                break;
            default:
                tf = false;
                break;
        }
    }

    return 0;
}

int ControllerAuth::fazerLogin(){
    int error = 0;
    stringstream ss;

    string cepefe, senha;

    Builder * builder;
    Controller * cntr;

    CPF cpf;
    Password password;

    while(true){
        try{
            interface->inform(interface->get_cpf);
            cepefe = interface->getString();
            cpf.set(cepefe);
            //interface->inform(identifier.get());//teste if ok
            break;
        }catch(invalid_argument ia){
            interface->inform(ia.what());
            error++;
            if(error>MAX_TOLERANCE){
                //throw(interface->err_tolerance);
            }
        }
    }

    while(true){
        try{
            interface->inform(interface->get_password);
            senha = interface->getString();
            password.set(senha);
            //interface->inform(identifier.get());//teste if ok
            break;
        }catch(invalid_argument ia){
            interface->inform(ia.what());
            error++;
            if(error>MAX_TOLERANCE){
                //throw(interface->err_tolerance);
            }
        }
    }

    User * user = new User();
    user->setCPF(cpf);
    user->setPassword(password);

    cmd->setUser(user);

    cmd->setCmd(cmd_auth::FAZERLOGIN);
    try{
        Persistence::Instanciate()->Executar(cmd);
    }catch(string str){
        throw(str);
    }

    interface->inform(ss.str());

    ss.str("");

    if (cmd->callback_count == 1) {

        // retira da pilha de resultado
        cmd->result.pop_back();

        interface->inform(interface->fazer_login_sucesso);

        interaction = new Interaction();
        interaction->setUser(user);

        builder = new builderSelector;
        cntr = builder->criar();
        try{
            cntr->execute();
        }catch(string e){
            ss.str("");
            ss << e << endl;
            interface->inform(ss.str());
        }catch(char* e){
            ss.str("");
            ss << e << endl;
            interface->inform(ss.str());
        }
    }
    else
        interface->inform(interface->fazer_login_falha);

    interface->inform(ss.str());

    return 0;
}

int ControllerAuth::cadastrar(){
    int error = 0;
    stringstream ss;

    string nome, senha, endereco, cepefe;

    Name name;
    Password password;
    Address address;
    CPF cpf;

    while(true){
        try{
            interface->inform(interface->get_name);
            nome = interface->getString();
            name.set(nome);
            //interface->inform(identifier.get());//teste if ok
            break;
        }catch(invalid_argument ia){
            interface->inform(ia.what());
            error++;
            if(error>MAX_TOLERANCE){
                //throw(interface->err_tolerance);
            }
        }
    }

    while(true){
        try{
            interface->inform(interface->get_password);
            senha = interface->getString();
            password.set(senha);
            //interface->inform(identifier.get());//teste if ok
            break;
        }catch(invalid_argument ia){
            interface->inform(ia.what());
            error++;
            if(error>MAX_TOLERANCE){
                //throw(interface->err_tolerance);
            }
        }
    }

    while(true){
        try{
            interface->inform(interface->get_address);
            endereco = interface->getString();
            address.set(endereco);
            //interface->inform(identifier.get());//teste if ok
            break;
        }catch(invalid_argument ia){
            interface->inform(ia.what());
            error++;
            if(error>MAX_TOLERANCE){
                //throw(interface->err_tolerance);
            }
        }
    }

    while(true){
        try{
            interface->inform(interface->get_cpf);
            cepefe = interface->getString();
            cpf.set(cepefe);
            //interface->inform(identifier.get());//teste if ok
            break;
        }catch(invalid_argument ia){
            interface->inform(ia.what());
            error++;
            if(error>MAX_TOLERANCE){
                //throw(interface->err_tolerance);
            }
        }
    }

    User * user = new User();

    user->setName(name);
    user->setAddress(address);
    user->setPassword(password);
    user->setCPF(cpf);
    cmd->setUser(user);

    cmd->setCmd(cmd_auth::CADASTRAR);
    try{
        Persistence::Instanciate()->Executar(cmd);
    }catch(string str){
        throw(str);
    }

    interface->inform(ss.str());

    ss.str("");
    ss << endl << interface->cadastrar_fim << cmd->callback_count << endl << endl;
    interface->inform(ss.str());

    return 0;
}
